package com.crop.back.common.utils;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

public class EncryptionUtil {
    private static final String ALGORITHM = "AES";
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
    private static final int KEY_SIZE = 256;
    private static final int IV_SIZE = 16;
    private static final Gson gson = new Gson();

    /**
     * 生成随机密钥
     */
    public static String generateKey() {
        try {
            KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM);
            keyGen.init(KEY_SIZE, new SecureRandom());
            SecretKey secretKey = keyGen.generateKey();
            return Base64.getEncoder().encodeToString(secretKey.getEncoded());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("生成密钥失败", e);
        }
    }

    /**
     * 生成随机IV
     * IV用于CBC模式下增加加密的随机性
     * 相同的明文+密钥，使用不同的IV会产生不同的密文
     */
    public static String generateIV() {
        byte[] iv = new byte[IV_SIZE];
        new SecureRandom().nextBytes(iv);
        return Base64.getEncoder().encodeToString(iv);
    }

    /**
     * 加密
     */
    public static String encrypt(String content, String key, String iv) {
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(key), ALGORITHM);
            IvParameterSpec ivSpec = new IvParameterSpec(Base64.getDecoder().decode(iv));

            cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
            byte[] encrypted = cipher.doFinal(content.getBytes("UTF-8"));
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            throw new RuntimeException("加密失败", e);
        }
    }

    /**
     * 解密
     */
    public static String decrypt(String encrypted, String key, String iv) {
        try {
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(key), ALGORITHM);
            IvParameterSpec ivSpec = new IvParameterSpec(Base64.getDecoder().decode(iv));

            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encrypted));
            return new String(decrypted, "UTF-8");
        } catch (Exception e) {
            throw new RuntimeException("解密失败", e);
        }
    }

    /**
     * 加密参数包装类
     */
    public static class EncryptionParams {
        private String key;
        private String iv;

        public EncryptionParams(String key, String iv) {
            this.key = key;
            this.iv = iv;
        }

        public String getKey() {
            return key;
        }

        public String getIv() {
            return iv;
        }

        public String toJson() {
            JsonObject json = new JsonObject();
            json.addProperty("key", key);
            json.addProperty("iv", iv);
            return gson.toJson(json);
        }
    }

    /**
     * 生成加密参数
     */
    public static EncryptionParams generateParams() {
        return new EncryptionParams(generateKey(), generateIV());
    }
}